const express = require('express');
const cors = require('cors');
const http2 = require('http2');

const app = express();

// CORS 配置
app.use(cors({
  origin: '*',
  methods: ['GET', 'POST', 'OPTIONS'],
  allowedHeaders: '*'
}));

// 处理 OPTIONS 预检请求
app.options('*', (req, res) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.header('Access-Control-Allow-Headers', '*');
  res.sendStatus(200);
});

// 代理 gRPC 请求到真实的 gRPC 服务器
app.use('/nuctech.DIS.Publisher.StatusPulishServer', (req, res) => {
  console.log('Proxying gRPC request to C# server:', req.method, req.url);
  console.log('Headers:', req.headers);
  
  // 解析 gRPC-Web 请求体
  let requestBody = Buffer.alloc(0);
  req.on('data', (chunk) => {
    requestBody = Buffer.concat([requestBody, chunk]);
  });
  
  req.on('end', () => {
    console.log('Request body length:', requestBody.length);
    console.log('Request body (base64):', requestBody.toString());
    
    // 解码 base64 请求体
    let gRPCBody = Buffer.alloc(0);
    if (requestBody.length > 0) {
      try {
        const base64Data = requestBody.toString();
        const decodedData = Buffer.from(base64Data, 'base64');
        console.log('Decoded data length:', decodedData.length);
        console.log('Decoded data (hex):', decodedData.toString('hex'));
        
        // 跳过 gRPC-Web 帧头（5字节：1字节标志 + 4字节长度）
        if (decodedData.length > 5) {
          gRPCBody = decodedData.slice(5);
          console.log('gRPC body length:', gRPCBody.length);
          console.log('gRPC body (hex):', gRPCBody.toString('hex'));
        }
      } catch (error) {
        console.error('Error decoding request body:', error);
      }
    }
    
    // 如果没有请求体，创建一个空的 protobuf 消息
    if (gRPCBody.length === 0) {
      // google.protobuf.Empty 是一个空消息，但需要正确的 protobuf 编码
      // 对于空消息，我们发送一个长度为 0 的消息
      // 在 gRPC 中，这通常是一个 5 字节的帧头 + 0 字节的消息体
      gRPCBody = Buffer.alloc(0);
      console.log('Created empty protobuf message');
    }
    
    // 创建 HTTP/2 客户端会话
    const client = http2.connect('http://localhost:22002');
    
    client.on('error', (err) => {
      console.error('HTTP/2 connection error:', err);
      res.status(500).json({ error: 'HTTP/2 connection error', details: err.message });
    });
    
    // 构建正确的 gRPC 路径
    // 从 /QueryDISStatus 转换为 /nuctech.DIS.Publisher.StatusPulishServer/QueryDISStatus
    const grpcPath = `/nuctech.DIS.Publisher.StatusPulishServer${req.url}`;
    console.log('gRPC path:', grpcPath);
    
    const headers = {
      ':method': req.method,
      ':path': grpcPath,
      ':scheme': 'http',
      ':authority': 'localhost:22002',
      'content-type': 'application/grpc',
      'te': 'trailers',
      'user-agent': 'grpc-node/1.0.0'
    };
    
    const proxyReq = client.request(headers);
    
    proxyReq.on('response', (headers) => {
      console.log('Received response from C# gRPC server:', headers[':status']);
      console.log('Response headers:', headers);
      
      // 设置 CORS 头
      res.header('Access-Control-Allow-Origin', '*');
      res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
      res.header('Access-Control-Allow-Headers', '*');
      res.header('Content-Type', 'application/grpc-web-text');
      
      // 设置 gRPC 状态
      const grpcStatus = headers['grpc-status'] || '0';
      const grpcMessage = headers['grpc-message'] || '';
      res.header('grpc-status', grpcStatus);
      res.header('grpc-message', grpcMessage);
    });
    
    let responseData = Buffer.alloc(0);
    
    proxyReq.on('data', (chunk) => {
      responseData = Buffer.concat([responseData, chunk]);
    });
    
    proxyReq.on('end', () => {
      console.log('Response data length:', responseData.length);
      if (responseData.length > 0) {
        console.log('Response data (hex):', responseData.toString('hex'));
        
        // C# gRPC 服务器返回的数据已经包含 gRPC 帧头
        // 直接使用原始数据，不需要重新编码
        const base64Response = responseData.toString('base64');
        console.log('Sending gRPC-Web response:', base64Response);
        console.log('Response frame (hex):', responseData.toString('hex'));
        res.send(base64Response);
      } else {
        // 空响应
        const flag = Buffer.from([0x00]);
        const length = Buffer.alloc(4);
        length.writeUInt32BE(0, 0);
        const webResponse = Buffer.concat([flag, length]);
        const base64Response = webResponse.toString('base64');
        console.log('Sending empty gRPC-Web response:', base64Response);
        res.send(base64Response);
      }
      
      // 关闭 HTTP/2 连接
      client.close();
    });
    
    proxyReq.on('error', (err) => {
      console.error('Proxy request error:', err);
      res.status(500).json({ error: 'Proxy request error', details: err.message });
      client.close();
    });

    // 发送请求体 - 对于 Empty 消息，发送空缓冲区
    console.log('Sending gRPC body to C# server, length:', gRPCBody.length);
    
    // 如果 gRPC 体为空，创建正确的 gRPC 帧格式
    if (gRPCBody.length === 0) {
      const flag = Buffer.from([0x00]); // 数据帧
      const length = Buffer.alloc(4);
      length.writeUInt32BE(0, 0);
      const grpcFrame = Buffer.concat([flag, length]);
      console.log('Sending gRPC frame (hex):', grpcFrame.toString('hex'));
      proxyReq.write(grpcFrame);
    } else {
      proxyReq.write(gRPCBody);
    }
    
    proxyReq.end();
  });
});

// 健康检查
app.get('/health', (req, res) => {
  res.json({ status: 'OK', message: 'Real gRPC Proxy Server is running' });
});

const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Real gRPC Proxy Server running on port ${PORT}`);
  console.log(`Proxying requests to http://localhost:22002 (HTTP/2)`);
  console.log(`Access health check at http://localhost:${PORT}/health`);
}); 